package org.mysfit.ctp4j.core;

import org.mysfit.ctp4j.core.service.MarketService;
import org.mysfit.ctp4j.infra.pojo.CtpUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ctp.thosttraderapi.CThostFtdcDepthMarketDataField;
import ctp.thosttraderapi.CThostFtdcMdApi;
import ctp.thosttraderapi.CThostFtdcMdSpi;
import ctp.thosttraderapi.CThostFtdcReqUserLoginField;
import ctp.thosttraderapi.CThostFtdcRspInfoField;
import ctp.thosttraderapi.CThostFtdcRspUserLoginField;
import ctp.thosttraderapi.CThostFtdcSpecificInstrumentField;

/**
 * 
 * @author long.gf
 *
 */
public class MyCThostFtdcMdSpi extends CThostFtdcMdSpi {
	private static final Logger LOGGER = LoggerFactory.getLogger(MyCThostFtdcMdSpi.class);
	
    private CtpUser ctpUser;
    private CThostFtdcMdApi mdApi;
    private MarketService marketService;
 
    public MyCThostFtdcMdSpi(CtpUser ctpUser, CThostFtdcMdApi mdapi, MarketService marketService){
        this.ctpUser = ctpUser;
        this.mdApi = mdapi;
        this.marketService = marketService;
    }
    
    @Override
    public void OnFrontConnected(){
    	LOGGER.info("OnFrontConnected");
        CThostFtdcReqUserLoginField pReqUserLoginField = new CThostFtdcReqUserLoginField();
        pReqUserLoginField.setBrokerID(this.ctpUser.getBrokerId());
        pReqUserLoginField.setUserID(this.ctpUser.getInvestorId());
        pReqUserLoginField.setPassword(this.ctpUser.getPassword());
        int requestId = (int) (Math.random() * 10000);
        mdApi.ReqUserLogin(pReqUserLoginField, requestId);
    }
 
    @Override
    public void OnRspUserLogin(CThostFtdcRspUserLoginField pRspUserLogin, CThostFtdcRspInfoField pRspInfo, int nRequestID, boolean bIsLast) {
    	LOGGER.info("OnRspUserLogin");
        if (pRspUserLogin != null) {
            LOGGER.info("登陆成功：BrokerID={}, UserID={}, RequestID={}",pRspUserLogin.getBrokerID(), pRspUserLogin.getUserID(), nRequestID);
        }
        if (pRspInfo.getErrorID() != 0){
        	LOGGER.error("登陆失败: ErrorID={}, ErrorMsg={}", pRspInfo.getErrorID(), pRspInfo.getErrorMsg());
        }
        int result =  mdApi.SubscribeMarketData(
        		this.ctpUser.getInstruementIds().trim().split(","), 
        		this.ctpUser.getInstruementIds().trim().split(",").length);
        if (result == 0) {
        	LOGGER.info("订阅成功：InstruementIds={}", this.ctpUser.getInstruementIds());
        }
        LOGGER.info("交易日" + this.mdApi.GetTradingDay());
    }
 
    @Override
    public void OnRspSubMarketData(CThostFtdcSpecificInstrumentField pSpecificInstrument, CThostFtdcRspInfoField RspInfo, int nRequestID, boolean bIsLast){
    	LOGGER.info("OnRspSubMarketData");
    	if (RspInfo.getErrorID() != 0){
    		LOGGER.error("订阅失败：InstrumentID={}, ErrorID={}, ErrorMsg={}",pSpecificInstrument.getInstrumentID(), RspInfo.getErrorID(), RspInfo.getErrorMsg());
        }
        super.OnRspSubMarketData(pSpecificInstrument,RspInfo,nRequestID,bIsLast);
    }
    
    @Override
    public void OnRspUnSubMarketData(CThostFtdcSpecificInstrumentField pSpecificInstrument, CThostFtdcRspInfoField pRspInfo, int nRequestID, boolean bIsLast) {
        LOGGER.info("OnRspUnSubMarketData");
        super.OnRspUnSubMarketData(pSpecificInstrument, pRspInfo, nRequestID, bIsLast);
    }
 
    @Override
    public void OnRtnDepthMarketData(CThostFtdcDepthMarketDataField pDepthMarketData) {
    	LOGGER.info("OnRtnDepthMarketData");
        if (pDepthMarketData != null) {
        	String timestamp = String.format("%s-%s:%d", pDepthMarketData.getTradingDay(), pDepthMarketData.getUpdateTime(), pDepthMarketData.getUpdateMillisec());
            LOGGER.info("合约代码[{}],最新价[{}],时间[{}]", pDepthMarketData.getInstrumentID(), pDepthMarketData.getLastPrice(), timestamp);
            marketService.saveData(pDepthMarketData);
        }else {
            LOGGER.info("pDepthMarketData is null");
        }
        super.OnRtnDepthMarketData(pDepthMarketData);
    }
    
    @Override
    public void OnFrontDisconnected(int nReason) {
        /*
         * 如果客户端到行情前置的无身份验证连接建立失败，这个函数被调用。其中的参数说明连接失败的原因
         */
    	LOGGER.info("OnFrontDisconnected");
    	LOGGER.error("前置服务断开连接, 返回错误码:{}", nReason);
        super.OnFrontDisconnected(nReason);
    }
    
    /**
     * 如果交易系统无法识别客户端发送的请求消息，就通过这个函数返回错误信息
     * @param pRspInfo
     * @param nRequestID
     * @param bIsLast
     */
    @Override
    public void OnRspError(CThostFtdcRspInfoField pRspInfo, int nRequestID, boolean bIsLast) {
    	LOGGER.info("OnRspError");
        LOGGER.error("ErrorID={},ErrorMsg={}", pRspInfo.getErrorID(), pRspInfo.getErrorMsg());
        super.OnRspError(pRspInfo, nRequestID, bIsLast);
    }
 
    /**
     * 如果超过一定时间在客户端和系统之间没有任何消息交换发生，这个函数会发送心跳用来说明客户端到系统服务器之间的连接是活跃的。
     * 目前此接口已经不再起效
     * @param nTimeLapse
     */
    @Override
    public void OnHeartBeatWarning(int nTimeLapse) {
        LOGGER.info("OnHeartBeatWarning");
        super.OnHeartBeatWarning(nTimeLapse);
    }
}
